<script lang="ts" setup>
import { computed, defineEmits } from 'vue';

import { usePreferences } from '@vben/preferences';

import { message } from 'ant-design-vue';
import { MdEditor, NormalToolbar } from 'md-editor-v3';

import { useUpload } from '#/components/upload/use-upload';
import { getFileUrlCode } from '#/utils/fileUtils';

import 'md-editor-v3/lib/style.css';

const props = defineProps({
  value: { type: String, default: '' },
  // 编辑器唯一 id，同一页面多次调用需传入不同 id
  id: { type: String, default: 'md-editor-single' },
  // 预览主题：default / github / vuepress / smart-blue
  preview: { type: String, default: 'vuepress' },
  // 代码主题：atom / vs / github / monokai 等
  code: { type: String, default: 'atom' },
  // 上传文件的参数
  params: { type: Object, default: () => ({ fileCategoriesCode: 'WZTPFJ' }) },
  // 是否启用图片上传功能
  enableUpload: { type: Boolean, default: true },
  // 上传文件类型限制
  uploadAccept: { type: String, default: '.jpg,.jpeg,.gif,.png,.webp' },
  // 编辑器高度
  height: { type: [String, Number], default: '600px' },
  // 最大文件大小 (MB)
  maxFileSize: { type: Number, default: 2 },
});

const emit = defineEmits(['update:value', 'save']);

const { isDark } = usePreferences();
const skinName = computed(() => {
  return isDark.value ? 'dark' : 'light';
});

const innerText = computed({
  get: () => props.value,
  set: (v) => emit('update:value', v),
});

// 工具栏定制 - 启用图片上传功能和复制功能
const toolbars = [
  'bold',
  'underline',
  'italic',
  'strikeThrough',
  '-',
  'title',
  'sub',
  'sup',
  'quote',
  'unorderedList',
  'orderedList',
  'task',
  '-',
  'codeRow',
  'code',
  'link',
  'image',
  'table',
  'mermaid',
  'katex',
  '-',
  'revoke',
  'next',
  'save',
  0, // 复制按钮（使用数字0作为自定义工具栏按钮的占位符）
  '=',
  'pageFullscreen',
  'fullscreen',
];

// 底部栏：只保留字数统计
const footers = ['markdownTotal', '='];

function handleSave(val: string) {
  emit('save', val);
}

// 复制内容到剪贴板
async function handleCopyContent() {
  try {
    if (!innerText.value) {
      message.warning('没有可复制的内容');
      return;
    }

    // 检查是否支持现代的 Clipboard API
    if (navigator.clipboard && window.isSecureContext) {
      await navigator.clipboard.writeText(innerText.value);
      message.success('内容已复制到剪贴板');
      return;
    }

    // 降级方案：使用现代的 Selection API
    try {
      const textarea = document.createElement('textarea');
      textarea.value = innerText.value;
      textarea.style.position = 'fixed';
      textarea.style.opacity = '0';
      textarea.style.left = '-9999px';
      textarea.style.top = '-9999px';
      document.body.append(textarea);

      // 选择文本
      textarea.focus();
      textarea.select();
      textarea.setSelectionRange(0, innerText.value.length);

      // 尝试使用现代的 execCommand（虽然已弃用，但作为最后的降级方案）
      const successful = document.execCommand('copy');
      textarea.remove();

      if (successful) {
        message.success('内容已复制到剪贴板');
      } else {
        throw new Error('复制命令执行失败');
      }
    } catch (fallbackError) {
      console.error('复制失败:', fallbackError);
      message.error('复制失败，请手动选择复制');

      // 最后的降级方案：显示文本供用户手动复制
      try {
        const textarea = document.createElement('textarea');
        textarea.value = innerText.value;
        textarea.style.position = 'fixed';
        textarea.style.top = '50%';
        textarea.style.left = '50%';
        textarea.style.transform = 'translate(-50%, -50%)';
        textarea.style.width = '80%';
        textarea.style.height = '200px';
        textarea.style.zIndex = '9999';
        textarea.style.padding = '10px';
        textarea.style.border = '2px solid #1890ff';
        textarea.style.backgroundColor = '#fff';
        textarea.readOnly = true;

        const label = document.createElement('div');
        label.textContent = '请手动选择并复制以下内容：';
        label.style.position = 'fixed';
        label.style.top = 'calc(50% - 150px)';
        label.style.left = '50%';
        label.style.transform = 'translateX(-50%)';
        label.style.zIndex = '9999';
        label.style.backgroundColor = '#1890ff';
        label.style.color = '#fff';
        label.style.padding = '5px 10px';
        label.style.borderRadius = '4px';

        const closeBtn = document.createElement('button');
        closeBtn.textContent = '关闭';
        closeBtn.style.position = 'fixed';
        closeBtn.style.top = 'calc(50% + 120px)';
        closeBtn.style.left = '50%';
        closeBtn.style.transform = 'translateX(-50%)';
        closeBtn.style.zIndex = '9999';
        closeBtn.style.padding = '5px 15px';
        closeBtn.style.backgroundColor = '#1890ff';
        closeBtn.style.color = '#fff';
        closeBtn.style.border = 'none';
        closeBtn.style.borderRadius = '4px';
        closeBtn.style.cursor = 'pointer';

        document.body.append(label);
        document.body.append(textarea);
        document.body.append(closeBtn);

        textarea.focus();
        textarea.select();

        closeBtn.addEventListener('click', () => {
          label.remove();
          textarea.remove();
          closeBtn.remove();
        });

        // 5秒后自动关闭
        setTimeout(() => {
          if (document.body.contains(label)) {
            label.remove();
            textarea.remove();
            closeBtn.remove();
          }
        }, 5000);
      } catch (manualError) {
        console.error('手动复制方案也失败了:', manualError);
        message.error('复制失败，请手动选择编辑器内容进行复制');
      }
    }
  } catch (error) {
    console.error('复制失败:', error);
    message.error('复制失败，请手动选择复制');
  }
}

// 处理文件上传 - 适配md-editor-v3的onUploadImg事件（兼容旧版本）
async function handleUpload(files: File[], callback: (urls: string[]) => void) {
  // 首先检查是否启用了上传功能
  if (!props.enableUpload) {
    console.log('图片上传功能已禁用');
    callback([]);
    return;
  }

  try {
    const { httpRequest } = useUpload(props.params);

    // 验证文件类型 - 使用更严格的验证
    const validFiles = files.filter((file) => {
      // 检查文件扩展名
      const fileName = file.name.toLowerCase();
      const validExtensions = ['.jpg', '.jpeg', '.gif', '.png', '.webp'];
      const hasValidExtension = validExtensions.some((ext) =>
        fileName.endsWith(ext),
      );

      // 检查MIME类型
      const hasValidMimeType = file.type.startsWith('image/');

      const isValid = hasValidExtension && hasValidMimeType;

      // 检查文件大小
      const maxSizeBytes = props.maxFileSize * 1024 * 1024; // 转换为字节
      const isValidSize = file.size <= maxSizeBytes;

      if (!isValid) {
        console.warn(
          `文件 ${file.name} 验证失败 - 扩展名: ${hasValidExtension}, MIME类型: ${hasValidMimeType}, 大小限制: ${isValidSize}`,
        );
      } else if (isValidSize) {
        console.log(
          `文件 ${file.name} 验证通过 - 类型: ${file.type}, 大小: ${(file.size / 1024 / 1024).toFixed(2)}MB`,
        );
      } else {
        console.warn(
          `文件 ${file.name} 大小超出限制 - 当前大小: ${(file.size / 1024 / 1024).toFixed(2)}MB, 限制: ${props.maxFileSize}MB`,
        );
      }

      return isValid && isValidSize;
    });

    if (validFiles.length === 0) {
      console.error('没有有效的图片文件');
      callback([]);
      return;
    }

    // 并发上传所有文件
    const uploadPromises = validFiles.map(async (file) => {
      try {
        console.log(
          `开始上传文件: ${file.name}, 类型: ${file.type}, 大小: ${file.size}`,
        );
        const fileInfo = await httpRequest(file);
        console.log(`文件 ${file.name} 上传成功，返回信息:`, fileInfo);

        const url = fileInfo.id
          ? getFileUrlCode(fileInfo.id, false, fileInfo.fileCategoriesCode)
          : fileInfo.url;
        console.log(`生成的URL: ${url}`);
        return url;
      } catch (error: any) {
        console.error(`文件 ${file.name} 上传失败:`, error);
        throw new Error(`上传失败: ${error.message}`);
      }
    });

    // 等待所有上传完成，使用Promise.allSettled避免一个失败影响其他
    console.log('等待所有文件上传完成...');
    const results = await Promise.allSettled(uploadPromises);
    console.log('上传结果:', results);

    // 收集成功的URL
    const urls = results
      .filter((result) => result.status === 'fulfilled')
      .map((result) => (result as PromiseFulfilledResult<string>).value);

    console.log('成功上传的URLs:', urls);

    // 统计失败的数量
    const failedCount = results.filter(
      (result) => result.status === 'rejected',
    ).length;

    if (failedCount > 0) {
      console.warn(`${failedCount} 个文件上传失败`);
    }

    // 回调函数返回URL数组
    console.log('调用callback函数，返回URLs:', urls);
    callback(urls);
  } catch (error) {
    console.error('markdown-editor 批量上传失败:', error);
    // 上传失败时回调空数组
    callback([]);
  }
}
</script>

<template>
  <div class="markdown-editor">
    <MdEditor
      :editor-id="id"
      v-model="innerText"
      :theme="skinName"
      :preview-theme="preview"
      :code-theme="code"
      :toolbars="toolbars"
      :footers="footers"
      :no-mermaid="false"
      :no-katex="false"
      :format-copied="true"
      :upload-accept="uploadAccept"
      :height="height"
      @on-save="handleSave"
      @on-upload-img="handleUpload"
    >
      <template #defToolbars>
        <NormalToolbar title="复制内容" @on-click="handleCopyContent">
          <template #trigger>
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="16"
              height="16"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
              stroke-linejoin="round"
              style="vertical-align: middle"
            >
              <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
              <path
                d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
              />
            </svg>
          </template>
        </NormalToolbar>
      </template>
    </MdEditor>
  </div>
</template>

<style lang="scss" scoped>
.markdown-editor {
  height: 100%;
  overflow: hidden;
  border: 1px solid #d9d9d9;
  border-radius: 6px;
  transition: border-color 0.3s;

  &:hover {
    border-color: #40a9ff;
  }

  :deep(.md-editor) {
    border: none;

    &.md-editor-dark {
      border-color: #434343;

      &:hover {
        border-color: #177ddc;
      }
    }
  }
}
</style>
